package org.eclipse.emf.extensions.microsoft;

import static java.text.MessageFormat.format;
import static org.eclipse.core.runtime.IStatus.ERROR;

import java.sql.Connection;
import java.sql.SQLException;

import org.eclipse.emf.db.Activator;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.extensions.DBSchema;
import org.eclipse.emf.extensions.IDBTable;
import org.eclipse.emf.extensions.IDBTableDescriptor;
import org.eclipse.emf.extensions.IDBTypeProvider;

import com.microsoft.sqlserver.jdbc.SQLServerDatabaseMetaData;
import com.microsoft.sqlserver.jdbc.SQLServerException;

public class MicrosoftSchema extends DBSchema {
    private static final String[] RESERVED_WORDS= { "ABSOLUTE", "EXEC", "OVERLAPS", "ACTION", "EXECUTE", "PAD", "ADA", "EXISTS", "PARTIAL", "ADD", "EXTERNAL",
            "PASCAL", "ALL", "EXTRACT", "POSITION", "ALLOCATE", "FALSE", "PRECISION", "ALTER", "FETCH", "PREPARE", "AND", "FIRST", "PRESERVE", "ANY", "FLOAT",
            "PRIMARY", "ARE", "FOR", "PRIOR", "AS", "FOREIGN", "PRIVILEGES", "ASC", "FORTRAN", "PROCEDURE", "ASSERTION", "FOUND", "PUBLIC", "AT", "FROM",
            "READ", "AUTHORIZATION", "FULL", "REAL", "AVG", "GET", "REFERENCES", "BEGIN", "GLOBAL", "RELATIVE", "BETWEEN", "GO", "RESTRICT", "BIT", "GOTO",
            "REVOKE", "BIT_LENGTH", "GRANT", "RIGHT", "BOTH", "GROUP", "ROLLBACK", "BY", "HAVING", "ROWS", "CASCADE", "HOUR", "SCHEMA", "CASCADED", "IDENTITY",
            "SCROLL", "CASE", "IMMEDIATE", "SECOND", "CAST", "IN", "SECTION", "CATALOG", "INCLUDE", "SELECT", "CHAR", "INDEX", "SESSION", "CHAR_LENGTH",
            "INDICATOR", "SESSION_USER", "CHARACTER", "INITIALLY", "SET", "CHARACTER_LENGTH", "INNER", "SIZE", "CHECK", "INPUT", "SMALLINT", "CLOSE",
            "INSENSITIVE", "SOME", "COALESCE", "INSERT", "SPACE", "COLLATE", "INT", "SQL", "COLLATION", "INTEGER", "SQLCA", "COLUMN", "INTERSECT", "SQLCODE",
            "COMMIT", "INTERVAL", "SQLERROR", "CONNECT", "INTO", "SQLSTATE", "CONNECTION", "IS", "SQLWARNING", "CONSTRAINT", "ISOLATION", "SUBSTRING",
            "CONSTRAINTS", "JOIN", "SUM", "CONTINUE", "KEY", "SYSTEM_USER", "CONVERT", "LANGUAGE", "TABLE", "CORRESPONDING", "LAST", "TEMPORARY", "COUNT",
            "LEADING", "THEN", "CREATE", "LEFT", "TIME", "CROSS", "LEVEL", "TIMESTAMP", "CURRENT", "LIKE", "TIMEZONE_HOUR", "CURRENT_DATE", "LOCAL",
            "TIMEZONE_MINUTE", "CURRENT_TIME", "LOWER", "TO", "CURRENT_TIMESTAMP", "MATCH", "TRAILING", "CURRENT_USER", "MAX", "TRANSACTION", "CURSOR", "MIN",
            "TRANSLATE", "DATE", "MINUTE", "TRANSLATION", "DAY", "MODULE", "TRIM", "DEALLOCATE", "MONTH", "TRUE", "DEC", "NAMES", "UNION", "DECIMAL",
            "NATIONAL", "UNIQUE", "DECLARE", "NATURAL", "UNKNOWN", "DEFAULT", "NCHAR", "UPDATE", "DEFERRABLE", "NEXT", "UPPER", "DEFERRED", "NO", "USAGE",
            "DELETE", "NONE", "USER", "DESC", "NOT", "USING", "DESCRIBE", "NULL", "VALUE", "DESCRIPTOR", "NULLIF", "VALUES", "DIAGNOSTICS", "NUMERIC",
            "VARCHAR", "DISCONNECT", "OCTET_LENGTH", "VARYING", "DISTINCT", "OF", "VIEW", "DOMAIN", "ON", "WHEN", "DOUBLE", "ONLY", "WHENEVER", "DROP", "OPEN",
            "WHERE", "ELSE", "OPTION", "WITH", "END", "OR", "WORK", "END-EXEC", "ORDER", "WRITE", "ESCAPE", "OUTER", "YEAR", "EXCEPT", "OUTPUT", "ZONE",
            "EXCEPTION" };

    MicrosoftSchema(Connection connection, EPackage pkg) throws SQLException {
        super(connection, pkg);
    }

    @Override
    protected IDBTable createTable(DBSchema schema, IDBTableDescriptor descriptor) {
        return new MicrosoftTable(schema, descriptor);
    }

    @Override
    public boolean requireIndexLength() {
        return false;
    }

    @Override
    protected String[] getReservedWords() {
        return RESERVED_WORDS;
    }

    @Override
    protected String getCreateTableSQL(IDBTableDescriptor descriptor) {
        return format("CREATE TABLE {0} (cdo_id int NOT NULL IDENTITY PRIMARY KEY, cdo_created bigint NOT NULL, cdo_container int)", descriptor.getName()); //$NON-NLS-1$
    }

    @Override
    public String getDBVersion() {
        try {
            return ((SQLServerDatabaseMetaData) getConnection().getMetaData()).getDatabaseProductVersion();
        } catch (SQLServerException e) {
            Activator.log(ERROR, "Failed getting database product version", e);
        } catch (SQLException e) {
            Activator.log(ERROR, "Failed getting database product version", e);
        }
        return "[N/A]";
    }

    @Override
    public IDBTypeProvider getTypeProvider() {
        return MicrosoftTypeProvider.INSTANCE;
    }
}
